package com.megvii.koala.net;

import com.android.volley.Request;
import com.android.volley.Response;
import com.megvii.corelib.net.Callback;
import com.megvii.koala.constance.ErrorCode;
import com.megvii.koala.data.GlobalData;
import com.megvii.koala.data.bean.BoxBean;
import com.megvii.koala.data.bean.CreatureBean;
import com.megvii.koala.data.bean.UpPictureBean;
import com.megvii.koala.data.bean.UserInfoBean;
import com.megvii.koala.data.bean.VisitorBean;
import com.megvii.koala.data.verify.CreatureVerifier;
import com.megvii.koala.guard.Box;
import com.megvii.koala.guard.BoxManager;
import com.megvii.koala.net.checkin.CheckInHistoryRequest;
import com.megvii.koala.net.checkin.CheckInHistoryResponse;
import com.megvii.koala.net.checkin.CheckInRequest;
import com.megvii.koala.net.checkin.CheckInResponse;
import com.megvii.koala.net.checkin.RecognizeHistoryRequest;
import com.megvii.koala.net.checkin.RecognizeHistoryResponse;
import com.megvii.koala.net.creature.AddCreatureRequest;
import com.megvii.koala.net.creature.AddCreatureResponse;
import com.megvii.koala.net.creature.DeleteCreatureRequest;
import com.megvii.koala.net.creature.DeleteCreatureResponse;
import com.megvii.koala.net.creature.EditCreatureRequest;
import com.megvii.koala.net.creature.EditCreatureResponse;
import com.megvii.koala.net.creature.GetCreaturesListRequest;
import com.megvii.koala.net.creature.GetCreaturesRequest;
import com.megvii.koala.net.creature.GetCreaturesResponse;
import com.megvii.koala.net.creature.UpdateCreatureAvatarRequest;
import com.megvii.koala.net.creature.UpdateCreatureAvatarResponse;
import com.megvii.koala.net.creature.UpdateCreatureDetectionRequest;
import com.megvii.koala.net.creature.UpdateCreatureDetectionResponse;
import com.megvii.koala.net.creature.UpdateCreaturePhotoIdListRequest;
import com.megvii.koala.net.creature.UpdateCreaturePhotoIdListResponse;
import com.megvii.koala.net.login.AdminLoginRequest;
import com.megvii.koala.net.login.AdminLoginResponse;
import com.megvii.koala.net.login.LoginRequest;
import com.megvii.koala.net.login.LoginResponse;
import com.megvii.koala.net.login.PadLoginRequest;
import com.megvii.koala.net.login.PadLoginResponse;
import com.megvii.koala.net.login.ResetPWRequest;
import com.megvii.koala.net.login.ResetPWResponse;
import com.megvii.koala.net.pad.PadSetInfoRequest;
import com.megvii.koala.net.pad.PadSetInfoResponse;
import com.megvii.koala.net.pad.PadSetInfoWithSwitchRequest;
import com.megvii.koala.net.recognize.RecognizeRequest;
import com.megvii.koala.net.recognize.RecognizeResponse;
import com.megvii.koala.net.update.AppUpdateRequest;
import com.megvii.koala.net.update.AppUpdateResponse;
import com.megvii.koala.net.user.EditUserInfoRequest;
import com.megvii.koala.net.user.EditUserInfoResponse;
import com.megvii.koala.net.user.UpdateAvatarRequest;
import com.megvii.koala.net.user.UpdateAvatarResponse;
import com.megvii.koala.net.user.UserInfoRequest;
import com.megvii.koala.net.user.UserInfoResponse;
import com.megvii.koala.net.visitor.AddVisitorRequest;
import com.megvii.koala.net.visitor.AddVisitorResponse;
import com.megvii.koala.net.visitor.DeleteVisitorDetectionRequest;
import com.megvii.koala.net.visitor.DeleteVisitorDetectionResponse;
import com.megvii.koala.net.visitor.DeleteVisitorRequest;
import com.megvii.koala.net.visitor.DeleteVisitorResponse;
import com.megvii.koala.net.visitor.EditVisitorRequest;
import com.megvii.koala.net.visitor.EditVisitorResponse;
import com.megvii.koala.net.visitor.GetVisitorsRequest;
import com.megvii.koala.net.visitor.GetVisitorsResponse;
import com.megvii.koala.net.visitor.InviteLinkRequest;
import com.megvii.koala.net.visitor.InviteLinkResponse;
import com.megvii.koala.net.visitor.PadAddVisitorRequest;
import com.megvii.koala.net.visitor.PadAddVisitorResponse;
import com.megvii.koala.net.visitor.UpdateVisitorAvatarRequest;
import com.megvii.koala.net.visitor.UpdateVisitorAvatarResponse;
import com.megvii.koala.net.visitor.UpdateVisitorDetectionRequest;
import com.megvii.koala.net.visitor.UpdateVisitorDetectionResponse;
import com.megvii.koala.net.visitor.history.GetVisitorHistoryRequest;
import com.megvii.koala.net.visitor.history.GetVisitorHistoryResponse;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by linyue on 15/12/21.
 */
public class NetAPI {
    private static NetAPI instance;

    private static KoalaHttpManager httpManager;

    private static KoalaHttpManager checkInHttpManager;

    private static Object loginCallbackObject;

    public static void init(KoalaHttpManager httpManager, KoalaHttpManager checkInHttpManager) {
        NetAPI.instance = new NetAPI();
        NetAPI.httpManager = httpManager;
        NetAPI.checkInHttpManager = checkInHttpManager;
    }

    public static void setUrlBase(String serverAddress) {
        httpManager.setUrlBase(serverAddress);
    }

    /**
     * 登陆请求
     *
     * @param username
     * @param password
     * @param serverAddress
     * @param callbackInstance
     * @param errorListener
     * @return
     */
    public static int requestLogin(String username, String password, String serverAddress,
                                   Object callbackInstance, Response.ErrorListener errorListener) {
        httpManager.setUrlBase(serverAddress);
        if (username == null || username.equals("")) {
            return ErrorCode.USERNAME_NULL;
        }
        if (password == null || password.equals("")) {
            return ErrorCode.PASSWORD_NULL;
        }
        //
        loginCallbackObject = callbackInstance;
        LoginRequest request = new LoginRequest(username, password);
        httpManager.requestJson(Request.Method.POST, request, LoginResponse.class, new NetAPI(),
                errorListener);
        return ErrorCode.NO_ERROR;
    }

    public static int requestAdminLogin(String username, String password, String serverAddress,
                                        Object callbackInstance, Response.ErrorListener errorListener) {
        httpManager.setUrlBase(serverAddress);
        if (username == null || username.equals("")) {
            return ErrorCode.USERNAME_NULL;
        }
        if (password == null || password.equals("")) {
            return ErrorCode.PASSWORD_NULL;
        }
        AdminLoginRequest request = new AdminLoginRequest(username, password);
        httpManager.requestJson(Request.Method.POST, request, AdminLoginResponse.class,
                callbackInstance, errorListener);
        return ErrorCode.NO_ERROR;
    }

    public static int requestPadLogin(String username, String password, String padId,
                                      int deviceType, String serverAddress, Object callbackInstance,
                                      Response.ErrorListener errorListener) {
        httpManager.setUrlBase(serverAddress);
        if (username == null || username.equals("")) {
            return ErrorCode.USERNAME_NULL;
        }
        if (password == null || password.equals("")) {
            return ErrorCode.PASSWORD_NULL;
        }
        //
        loginCallbackObject = callbackInstance;
        PadLoginRequest request = new PadLoginRequest(username, password, padId, deviceType);
        httpManager.requestJson(Request.Method.POST, request, PadLoginResponse.class, new NetAPI(),
                errorListener);
        return ErrorCode.NO_ERROR;
    }

    /**
     * 重置密码请求
     *
     * @param password
     * @param passwordRepeat
     * @param callbackInstance
     * @param errorListener
     * @return
     */
    public static int requestResetPassword(String password, String passwordRepeat,
                                           Object callbackInstance, Response.ErrorListener errorListener) {
        if (password.equals("")) {
            return ErrorCode.PASSWORD_NULL;
        } else if (!password.equals(passwordRepeat)) {
            return ErrorCode.REPEAT_PASSWORD_ILLEGAL;
        } else {
            ResetPWRequest request = new ResetPWRequest(password, passwordRepeat);
            httpManager.requestJson(Request.Method.POST, request, ResetPWResponse.class,
                    callbackInstance, errorListener);
            return ErrorCode.NO_ERROR;
        }
    }

    /**
     * 获取此用户个人信息的请求
     *
     * @param callbackInstance
     * @param errorListener
     */
    public static void requestUserInfo(Object callbackInstance,
                                       Response.ErrorListener errorListener) {
        UserInfoRequest request = new UserInfoRequest();
        httpManager
                .requestJson(Request.Method.GET, request, UserInfoResponse.class, callbackInstance,
                        errorListener);
    }

    /**
     * 获取刷脸打卡的历史
     *
     * @param startTimestamp   开始时间的Unix时间戳，毫秒
     * @param endTimestamp     结束时间的Unix时间戳，毫秒
     * @param state
     * @param callbackInstance
     * @param errorListener
     */
    public static void requestCheckInHisroty(long startTimestamp, long endTimestamp, int state,
                                             Object callbackInstance, Response.ErrorListener errorListener) {
        CheckInHistoryRequest request = new CheckInHistoryRequest((int) (startTimestamp / 1000),
                (int) (endTimestamp / 1000), state);
        httpManager.requestJson(Request.Method.GET, request, CheckInHistoryResponse.class,
                callbackInstance, errorListener);
    }

    /**
     *
     *
     * @param startTimestamp 开始时间的
     * @param endTimestamp
     * @param state
     */

    /**
     * 获取一天内的刷脸记录
     *
     * @param date
     * @param callbackInstance
     * @param errorListener
     */
    public static void requestRecognizeHistory(long date, Object callbackInstance,
                                               Response.ErrorListener errorListener) {
        RecognizeHistoryRequest request = new RecognizeHistoryRequest((int) (date / 1000));
        httpManager.requestJson(Request.Method.GET, request, RecognizeHistoryResponse.class,
                callbackInstance, errorListener);
    }

    public static void requestUploadUserHeadImage(byte[] imageData, Object callbackInstance,
                                                  Response.ErrorListener errorListener) {
        UpdateAvatarRequest request = new UpdateAvatarRequest(imageData);
        httpManager.requestMultipart(Request.Method.POST, request, UpdateAvatarResponse.class,
                callbackInstance, errorListener);
    }

    public static void requestEditUserInfo(UserInfoBean userInfo, Object callbackInstance,
                                           Response.ErrorListener errorListener) {
        EditUserInfoRequest request = new EditUserInfoRequest(userInfo);
        httpManager.requestJson(Request.Method.PUT, request, EditUserInfoResponse.class,
                callbackInstance, errorListener);
    }

    public static void requestGetVisitors(Object callbackInstance,
                                          Response.ErrorListener errorListener) {
        GetVisitorsRequest request = new GetVisitorsRequest();
        httpManager.requestJson(Request.Method.GET, request, GetVisitorsResponse.class,
                callbackInstance, errorListener);
    }

    public static void requestEditVisitor(VisitorBean visitor, Object callbackInstance,
                                          Response.ErrorListener errorListener) {
        EditVisitorRequest request = new EditVisitorRequest(visitor);
        httpManager.requestJson(Request.Method.PUT, request, EditVisitorResponse.class,
                callbackInstance, errorListener);
    }

    public static void requestDeleteVisitor(String visitorId, Object callbackInstance,
                                            Response.ErrorListener errorListener) {
        DeleteVisitorRequest request = new DeleteVisitorRequest(visitorId);
        httpManager.requestJson(Request.Method.DELETE, request, DeleteVisitorResponse.class,
                callbackInstance, errorListener);
    }

    public static void requestUploadVisitorHeadImage(String visitorId, byte[] imageData,
                                                     Object callbackInstance, Response.ErrorListener errorListener) {
        UpdateVisitorAvatarRequest request = new UpdateVisitorAvatarRequest(visitorId, imageData);
        httpManager
                .requestMultipart(Request.Method.POST, request, UpdateVisitorAvatarResponse.class,
                        callbackInstance, errorListener);
    }

    public static void requestUpdateVisitorDetection(byte[] photo, String visitorId,
                                                     String oldPhotoId, Object callbackInstance, Response.ErrorListener errorListener) {
        UpdateVisitorDetectionRequest request = new UpdateVisitorDetectionRequest(photo, visitorId,
                oldPhotoId);
        httpManager.requestMultipart(Request.Method.POST, request,
                UpdateVisitorDetectionResponse.class, callbackInstance, errorListener);
    }

    public static void requestDeleteVisitorDetection(String photoId, Object callbackInstance,
                                                     Response.ErrorListener errorListener) {
        DeleteVisitorDetectionRequest request = new DeleteVisitorDetectionRequest(photoId);
        httpManager
                .requestJson(Request.Method.DELETE, request, DeleteVisitorDetectionResponse.class,
                        callbackInstance, errorListener);
    }

    public static void requestAddVisitor(String name, boolean isVip, long start_time, long end_time,
                                         int purpose, String description, String remark, Object callbackInstance,
                                         Response.ErrorListener errorListener) {
        AddVisitorRequest request = new AddVisitorRequest(name, isVip, (int) (start_time / 1000),
                (int) (end_time / 1000), purpose, description, remark);
        httpManager.requestJson(Request.Method.POST, request, AddVisitorResponse.class,
                callbackInstance, errorListener);
    }

    public static void requestVisitorHistory(String visitorId, String startId, int pageSize,
                                             Object callbackInstance, Response.ErrorListener errorListener) {
        GetVisitorHistoryRequest request = new GetVisitorHistoryRequest(visitorId, startId,
                pageSize);
        httpManager.requestJson(Request.Method.GET, request, GetVisitorHistoryResponse.class,
                callbackInstance, errorListener);
    }

    public static boolean requestCheckIn(String userId, byte[] image, Object callbackInstance,
                                         Response.ErrorListener errorListener) {
        Box box = GlobalData.instance().boxManager.getRandomValidBox();
        if (box == null) {
            GlobalData.instance().boxManager.validate();
            return false;
        }
        //TODO 这里容易出bug，连续两个不同ip的请求
        checkInHttpManager.setUrlBase("http://" + box.address + ":8866");
        CheckInRequest request = new CheckInRequest(userId, image);
        checkInHttpManager.requestMultipart(Request.Method.POST, request, CheckInResponse.class,
                callbackInstance, errorListener);
        return true;
    }

    public static void requestInviteLink(String visitorId, Object callbackInstance,
                                         Response.ErrorListener errorListener) {
        InviteLinkRequest request = new InviteLinkRequest(visitorId);
        httpManager.requestJson(Request.Method.GET, request, InviteLinkResponse.class,
                callbackInstance, errorListener);
    }

    public static int requestPadAddVisitor(byte[] photo, String name, int purpose,
                                           String interviewee, long start_time, long end_time, String come_from, boolean isVip,
                                           String phone, String description, String remark, Object callbackInstance,
                                           Response.ErrorListener errorListener) {
        int errorCode = CreatureVerifier
                .veryfyAddVisitor(name, interviewee, come_from, phone, description, remark,
                        purpose);
        if (errorCode != ErrorCode.NO_ERROR) {
            return errorCode;
        }
        PadAddVisitorRequest request = new PadAddVisitorRequest(photo, name, purpose, interviewee,
                (int) (start_time / 1000), (int) (end_time / 1000), come_from, isVip, phone,
                description, remark);
        httpManager.requestMultipart(Request.Method.POST, request, PadAddVisitorResponse.class,
                callbackInstance, errorListener);
        return ErrorCode.NO_ERROR;
    }

    public static boolean requestRecognize(byte[] image, String screenToken,
                                           Object callbackInstance, Response.ErrorListener errorListener) {
        Box box = GlobalData.instance().boxManager.getRandomValidBox();
        if (box == null) {
            GlobalData.instance().boxManager.validate();
            return false;
        }
        //TODO 这里容易出bug，连续两个不同ip的请求
        checkInHttpManager.setUrlBase("http://" + box.address + ":8866");
        RecognizeRequest request = new RecognizeRequest(image, screenToken);
        checkInHttpManager.requestMultipart(Request.Method.POST, request, RecognizeResponse.class,
                callbackInstance, errorListener);
        return true;
    }

    public static void requestGetCreatures(Object callbackObject,
                                           Response.ErrorListener errorListener) {
        GetCreaturesRequest request = new GetCreaturesRequest();
        httpManager.requestJson(Request.Method.GET, request, GetCreaturesResponse.class,
                callbackObject, errorListener);
    }

    /**
     * neo 分页获取用户列表
     */
    public static void requestGetCreaturesList(String category, String name, String order, int page, int size,
                                               Object callbackObject,
                                               Response.ErrorListener errorListener) {
        GetCreaturesListRequest request = new GetCreaturesListRequest(category, name, order, page, size);
        httpManager.requestJson(Request.Method.GET, request, GetCreaturesResponse.class,
                callbackObject, errorListener);
    }

    public static void requestAddCreature(CreatureBean creature, Object callbackObject,
                                          Response.ErrorListener errorListener) {
        AddCreatureRequest request = new AddCreatureRequest(creature);
        httpManager.requestJson(Request.Method.POST, request, AddCreatureResponse.class,
                callbackObject, errorListener);
    }

    public static void requestEditCreature(CreatureBean creature,  Object callbackObject,
                                           Response.ErrorListener errorListener) {
        EditCreatureRequest request = new EditCreatureRequest(creature);
        httpManager.requestPureJson(Request.Method.PUT, request, EditCreatureResponse.class,
                callbackObject, errorListener);
    }

//    public static void requestEditCreature(CreatureBean creature, String property, Object callbackObject,
//                                           Response.ErrorListener errorListener) {
//        EditCreatureRequest request = new EditCreatureRequest(creature, property);
//        httpManager.requestPureJson(Request.Method.PUT, request, EditCreatureResponse.class,
//                callbackObject, errorListener);
//    }

    public static void requestDeleteCreature(String id, Object callbackObject,
                                             Response.ErrorListener errorListener) {
        DeleteCreatureRequest request = new DeleteCreatureRequest(id);
        httpManager.requestJson(Request.Method.DELETE, request, DeleteCreatureResponse.class,
                callbackObject, errorListener);
    }

    public static void requestUploadCreatureHeadImage(String subjectId, byte[] imageData,
                                                      Object callbackInstance, Response.ErrorListener errorListener) {
        UpdateCreatureAvatarRequest request = new UpdateCreatureAvatarRequest(subjectId, imageData);
        httpManager
                .requestMultipart(Request.Method.POST, request, UpdateCreatureAvatarResponse.class,
                        callbackInstance, errorListener);
    }

    public static void requestUpdateCreatureDetection(byte[] photo, String subjectId,
                                                      Object callbackInstance, Response.ErrorListener errorListener) {
        UpdateCreatureDetectionRequest request = new UpdateCreatureDetectionRequest(photo,
                subjectId);
        httpManager.requestMultipart(Request.Method.POST, request,
                UpdateCreatureDetectionResponse.class, callbackInstance, errorListener);
    }

    public static void requestUpdateCreaturePhotoIdList(CreatureBean creature,
                                                        Object callbackInstance, Response.ErrorListener errorListener) {
        UpdateCreaturePhotoIdListRequest request = new UpdateCreaturePhotoIdListRequest();
        request.id = creature.id;
        request.photo_ids = new ArrayList<>();
        if (creature.photos != null) {
            for (UpPictureBean pic : creature.photos) {
                request.photo_ids.add(Integer.valueOf(pic.id));
            }

        }
        httpManager.requestPureJson(Request.Method.PUT, request,
                UpdateCreaturePhotoIdListResponse.class, callbackInstance, errorListener);
    }

    public static void requestPadSetInfo(String padId, String box_token, String position,
                                         Object callbackInstance, Response.ErrorListener errorListener) {
        PadSetInfoRequest request = new PadSetInfoRequest(padId, box_token, position);
        httpManager.requestJson(Request.Method.PUT, request, PadSetInfoResponse.class,
                callbackInstance, errorListener);
    }

    /**
     * 平安银行设置pad信息接口，提交switcher信息
     *
     * @param padId
     * @param box_token
     * @param position
     * @param network_switcher
     * @param network_switcher_token
     * @param callbackInstance
     * @param errorListener
     */
    public static void requestPadSetInfoWithSwitcher(String padId, String box_token, String position,
                                                     String network_switcher, String network_switcher_token,
                                                     Object callbackInstance, Response.ErrorListener errorListener) {
        PadSetInfoWithSwitchRequest request = new PadSetInfoWithSwitchRequest(padId, box_token, position, network_switcher, network_switcher_token);
        httpManager.requestJson(Request.Method.PUT, request, PadSetInfoResponse.class,
                callbackInstance, errorListener);
    }

    public static void requestAppUpdate(String appType, String currentVersion,
                                        Object callbackInstance, Response.ErrorListener errorListener) {
        AppUpdateRequest request = new AppUpdateRequest(appType, currentVersion);
        httpManager
                .requestJson(Request.Method.GET, request, AppUpdateResponse.class, callbackInstance,
                        errorListener);
    }

    @Callback(clazz = LoginResponse.class)
    public void onLoginResponse(LoginResponse response) {
        if (response.code == 0) {
            updateBoxes(response.data.boxes);
        }
        checkInHttpManager.register(loginCallbackObject);
        checkInHttpManager.onResponse(response);
        checkInHttpManager.unregister(loginCallbackObject);
    }

    @Callback(clazz = PadLoginResponse.class)
    public void onPadLoginResponse(PadLoginResponse response) {
        if (response.code == 0) {
            updateBoxes(response.data.boxes);
        }
        checkInHttpManager.register(loginCallbackObject);
        checkInHttpManager.onResponse(response);
        checkInHttpManager.unregister(loginCallbackObject);
    }

    private void updateBoxes(List<BoxBean> boxes) {
        BoxManager boxManager = GlobalData.instance().boxManager;
        boxManager.clear();
        for (BoxBean box : boxes) {
            boxManager.addBox(new Box(box.id, box.box_address, box.box_token, box.company_id,
                    box.current_version));
        }
        boxManager.validate();
    }
}
